package core

type Blockchain struct {
	Headers   []*Header
	Store     Storage
	validator Validator
}

func NewBlockchain(genesis *Block) (*Blockchain, error) {
	bc := &Blockchain{
		Headers: make([]*Header, 0),
		Store:   NewBlockStore(),
	}
	// Default Validator
	bc.validator = NewBlockValidator(bc)
	err := bc.AddBlockWithoutValidation(genesis)

	return bc, err
}

func (bc *Blockchain) SetValidator(v Validator) {
	bc.validator = v
}

func (bc *Blockchain) Height() uint32 {
	return uint32(len(bc.Headers) - 1)
}

func (bc *Blockchain) AddBlock(b *Block) error {
	if err := bc.validator.ValidateBlock(b); err != nil {
		return err
	}

	return bc.AddBlockWithoutValidation(b)
}

func (bc *Blockchain) HasBlock(height uint32) bool {
	return height <= bc.Height()
}

func (bc *Blockchain) AddBlockWithoutValidation(b *Block) error {
	bc.Headers = append(bc.Headers, &b.Header)
	return bc.Store.Put(b)
}
